home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / dkbuts.zip / DXF2DKB.C < prev    next >
C/C++ Source or Header  |  1991-05-16  |  17KB  |  520 lines

  1. /* AutoCAD DXF file to DKB Data File Converter                        */
  2. /* Version 1.0 By Aaron A. Collins.  Written 8/13/90                  */
  3. /* Version 1.01 Modified to work with DKB 2.10 By Drew Wells 3/20/91  */
  4. /* This program is released to the public domain.                     */
  5. /*--------------------------------------------------------------------*/
  6. /* Version History                                                    */    
  7. /*--------------------------------------------------------------------*/ 
  8. /*  8/19/90 AC Wrote original program.
  9.  *  3/20/91 DW Put colors inside texture block for DKB 2.10.
  10.  *          DW Removed line INCLUDE "Basicshapes.dat".
  11.  *            DW Added additional comment docs at top of DKB outfile.
  12.  *          DW Added additional stats as to what DXF types were found.
  13.  *  4/29/91 AC Modified usage message and header semantics a bit.
  14.  *  5/15/91 AC Removed IBM-ness of filenames/extensions
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20.  
  21. #define BUFSIZE    2048
  22. #define FABS(x) ((x<0.0)?-x:x)
  23.  
  24. int getline (void);
  25. void writeobj (void);
  26. void finishobj (int color);
  27. void lookupcolor (int color, double *red, double *green, double *blue);
  28. int checkdegen(int a, int b, int c);
  29.  
  30. int groupcode;
  31. char linbuf[BUFSIZE];
  32. FILE *infile, *outfile;
  33. long primitives = 0L, degenerates = 0L;
  34. long num_triangles = 0L, num_points = 0L, num_circles = 0L, num_traces = 0L,
  35.      num_solids = 0L, num_lines = 0L, num_3dlines = 0L, num_3dfaces = 0L;
  36. char curobj[80];
  37. int curcolor;
  38. double curthick;
  39. double xcoords[10];
  40. double ycoords[10];
  41. double zcoords[10];
  42. double doubles[10];
  43. double angles[10];
  44. int ints[10];
  45. double max_x, max_y, max_z, min_x, min_y, min_z;
  46.  
  47.  
  48. void main(argc, argv)
  49. int argc;
  50. char *argv[];
  51. {
  52.     char *index;
  53.  
  54.     printf("\n\nAutoCad DXF to DKB Data file Translator\n");
  55.     printf("Version 1.0  Written By Aaron A. Collins, 8/13/90\n");
  56.     printf("Version 1.01 Modifications  By Drew Wells 3/20/91\n");
  57.     printf("Version 1.02 Modifications By Aaron A. Collins 3/20/91\n");
  58.     printf("Version 1.03 Modifications By Aaron A. Collins 5/15/91\n");
  59.     printf("* Type DXF2DKB with no arguments for more info. *\n");
  60.     printf("This program is released to the public domain.\n\n");
  61.     if (argc != 3)
  62.     {
  63.         printf("Usage:  %s InputFile OutputFile\n\n", argv[0]);
  64.                 
  65.         printf("DXF2DKB does a minimal conversion of AutoCad DXF files into DKB data format.\n");
  66.         printf("The following DXF primitives are currently supported:\n");
  67.         printf("\t3D Faces\tTriangles\tPoints\n");
  68.         printf("\t3D Lines\tCircles  \tSolids\n");
  69.         printf("\tLines   \tTraces\n");
  70.         printf("The DKB Raytracer is available on Compuserve's COMART forum lib 16 and\n");
  71.         printf("The \"You Can Call Me RAY\" Raytracing BBS at (708) 358-5611.\n");
  72.         printf("C source code for this utility is also available at those locations.\n");
  73.  
  74.         exit(1);
  75.     }
  76.     if (!(infile = fopen(argv[1], "r")))
  77.     {
  78.         printf("Cannot open input file %s!\n", argv[1]);
  79.         exit(1);
  80.     }
  81.  
  82.     if (!(outfile = fopen(argv[2], "w")))
  83.     {
  84.         printf("Cannot create output file %s!\n", argv[2]);
  85.         fclose(infile);
  86.         exit(1);
  87.     }
  88.  
  89.     printf("\nPlease wait; Processing...");
  90.     fprintf(outfile, "{ This file is for use with the DKB Ray Tracer.}\n");
  91.     fprintf(outfile, "{ %s: Converted from AutoCad DXF File: %s }\n\n", argv[2], argv[1]);
  92.     fprintf(outfile, "{ This is a composite object description for use with the DKB }\n");
  93.     fprintf(outfile, "{ Ray Tracer. It does not include viewpoint or light source desc-}\n");
  94.     fprintf(outfile, "{ riptions. It uses the Dull texture from textures.dat and it }\n");
  95.     fprintf(outfile, "{ may use Cylinder_Z from shapes.dat. }\n");
  96.     fprintf(outfile, "{ To use this file as an include file uncomment the DECLARE line }\n");
  97.     fprintf(outfile, "{ and change DxfObject to an appropriate name.}\n\n");
  98.     fprintf(outfile, "INCLUDE \"shapes.dat\"\n");
  99.     fprintf(outfile, "INCLUDE \"colors.dat\"\n");
  100.     fprintf(outfile, "INCLUDE \"textures.dat\"\n\n");
  101.     fprintf(outfile, "{ DECLARE DxfObject = }\n",argv[2]);
  102.         
  103.     fprintf(outfile, "COMPOSITE\n");
  104.  
  105.     curobj[0] = '\0';    /* not working on any object currently */
  106.     curcolor = 7;        /* and it also doesn't have a color yet... */
  107.     max_x = max_y = max_z =  -10000000.0;    /* init bounding limits */
  108.     min_x = min_y = min_z =   10000000.0;
  109.  
  110. find:    while (!feof(infile))    /* run file up to the "ENTITIES" section */
  111.     {
  112.         if (getline())        /* get a group code and a line */
  113.             goto stopit;
  114.         if (groupcode == 0)    /* file section mark */
  115.         {
  116.             if (strstr(linbuf, "EOF"))
  117.                 goto stopit;
  118.             if (strstr(linbuf, "SECTION"))
  119.             {
  120.                 if (getline())
  121.                     goto stopit;
  122.                 if (groupcode != 2)
  123.                     continue;
  124.                 if (strstr(linbuf, "ENTITIES"))
  125.                     break;
  126.             }
  127.         }
  128.     }
  129.     while (!feof(infile))        /* scan ENTITIES section */
  130.     {
  131.         if (getline())        /* get a group code and a line */
  132.             break;
  133.         if (groupcode < 10)    /* cardinal group codes */
  134.         {
  135.             switch(groupcode)
  136.             {
  137.                 case 0: /* start of entity, table, file sep */
  138.                     if (strstr(linbuf, "EOF"))
  139.                     {
  140.                         writeobj(); /* dump object */
  141.                         goto stopit;
  142.                     }
  143.                     if (strstr(linbuf, "ENDSEC"))
  144.                     {
  145.                         writeobj(); /* dump object */
  146.                         goto find;
  147.                     }
  148.                     writeobj();    /* dump old object */
  149.                     curobj[0] = '\0'; /* reset object */
  150.                     curcolor = 7;
  151.                     strcpy(curobj, linbuf);    /* get new */
  152.                     break;
  153.                 case 1:    /* primary text value for entity (?)*/
  154.                     break;
  155.                 case 2: /* block name, attribute tag, etc */
  156.                 case 3:    /* other names */
  157.                 case 4:
  158.                     break;
  159.                 case 5:    /* entity handle (hex string) */
  160.                     break;
  161.                 case 6: /* line type name */
  162.                     break;
  163.                 case 7: /* text style name */
  164.                     break;
  165.                 case 8: /* layer name */
  166.                     break;
  167.                 case 9: /* variable name ID (only in header)*/
  168.                     break;
  169.             }
  170.         }
  171.         else if (groupcode >= 10 && groupcode < 19) /* Some X coord */
  172.         {
  173.             sscanf(linbuf, "%f", &(xcoords[groupcode-10]));
  174.             if (xcoords[groupcode-10] > max_x)
  175.                 max_x = xcoords[groupcode-10];
  176.             if (xcoords[groupcode-10] < min_x)
  177.                 min_x = xcoords[groupcode-10];
  178.         }
  179.         else if (groupcode >= 20 && groupcode < 29) /* Some Y coord */
  180.         {
  181.             sscanf(linbuf, "%f", &(ycoords[groupcode-20]));
  182.             if (ycoords[groupcode-20] > max_y)
  183.                 max_y = ycoords[groupcode-20];
  184.             if (ycoords[groupcode-20] < min_y)
  185.                 min_y = ycoords[groupcode-20];
  186.         }
  187.         else if (groupcode >= 30 && groupcode < 38) /* Some Z coord */
  188.         {
  189.             sscanf(linbuf, "%f", &(zcoords[groupcode-30]));
  190.             if (zcoords[groupcode-30] > max_z)
  191.                 max_z = zcoords[groupcode-30];
  192.             if (zcoords[groupcode-30] < min_z)
  193.                 min_z = zcoords[groupcode-30];
  194.         }
  195.         else if (groupcode == 38) /* entity elevation if nonzero */
  196.         {
  197.         }
  198.         else if (groupcode == 39) /* entity thickness if nonzero */
  199.         {
  200.         }
  201.         else if (groupcode >= 40 && groupcode < 49) /* misc doubles */
  202.         {
  203.             sscanf(linbuf, "%f", &(doubles[groupcode-40]));
  204.         }
  205.         else if (groupcode == 49) /* repeated value groups */
  206.         {
  207.         }
  208.         else if (groupcode >= 50 && groupcode < 59) /* misc angles */
  209.         {
  210.             sscanf(linbuf, "%f", &(angles[groupcode-50]));
  211.         }
  212.         else if (groupcode == 62) /* Color number */
  213.         {
  214.             sscanf(linbuf, "%6d", &curcolor);
  215.         }
  216.         else if (groupcode == 66) /* "entities follow" flag */
  217.         {
  218.         }
  219.         else if (groupcode >= 70 && groupcode < 79) /* misc ints */
  220.         {
  221.             sscanf(linbuf, "%f", &(ints[groupcode-70]));
  222.         }
  223.         else if (groupcode == 210 || groupcode == 220 || groupcode == 230)
  224.         {    /* X, Y, Z components of extrusion direction */
  225.         }
  226.     }
  227. stopit: fprintf(outfile, "  BOUNDED_BY\n    INTERSECTION\n");
  228.     fprintf(outfile, "      PLANE <1.0  0.0  0.0> %1.04f END_PLANE\n", FABS(max_x) * 1.01);
  229.     fprintf(outfile, "      PLANE <-1.0 0.0  0.0> %1.04f END_PLANE\n", FABS(min_x) * 1.01);
  230.     fprintf(outfile, "      PLANE <0.0  1.0  0.0> %1.04f END_PLANE\n", FABS(max_y) * 1.01);
  231.     fprintf(outfile, "      PLANE <0.0 -1.0  0.0> %1.04f END_PLANE\n", FABS(min_y) * 1.01);
  232.     fprintf(outfile, "      PLANE <0.0  0.0  1.0> %1.04f END_PLANE\n", FABS(max_z) * 1.01);
  233.     fprintf(outfile, "      PLANE <0.0  0.0 -1.0> %1.04f END_PLANE\n", FABS(min_z) * 1.01);
  234.     fprintf(outfile, "    END_INTERSECTION\n  END_BOUND\nEND_COMPOSITE\n");
  235.     fclose(infile);
  236.     fflush(outfile);
  237.     fclose(outfile);
  238.     printf("Finished.\nTotal DKB objects written to output file: %ld\n\n", primitives);
  239.     printf("Total degenerate triangles removed from scene: %ld\n\n", degenerates);
  240.         
  241.     printf ("X bounding values range from %f to %f\n", min_x, max_x);
  242.     printf ("Y bounding values range from %f to %f\n", min_y, max_y);
  243.     printf ("Z bounding values range from %f to %f\n", min_z, max_z);
  244.     printf("\n\t\t\t--- DXF Stats ---\n");
  245.     printf("3D Faces = \t%ld\tTriangles = \t%ld\tPoints = \t%ld\n",num_3dfaces,num_triangles,num_points);
  246.     printf("3D Lines = \t%ld\tCircles   = \t%ld\tSolids = \t%ld\n",num_3dlines,num_circles,num_solids);
  247.     printf("Lines    = \t%ld\tTraces    = \t%ld\n",num_lines,num_traces);
  248.     exit(0);
  249. }
  250.  
  251.  
  252. int getline()        /* read a group code and the next line from infile */
  253. {
  254.     fgets(linbuf, BUFSIZE, infile);    /* get a line from .DXF */
  255.     if (feof(infile))
  256.         return(1);
  257.     sscanf(linbuf, "%3d", &groupcode);  /* scan out group code */
  258.     fgets(linbuf, BUFSIZE, infile);    /* get a line from .DXF */
  259.     if (feof(infile))
  260.         return(1);
  261.     return(0);
  262. }
  263.  
  264. void writeobj()    /* dump out current object we should have all info on */
  265. {
  266.     if (strstr(curobj, "LINE"))        /* a VERY skinny triangle! */
  267.     {
  268.         if (xcoords[0] == xcoords[1] && ycoords[0] == ycoords[1] && zcoords[0] == zcoords[1])
  269.         {
  270.             degenerates++;
  271.             return;
  272.         }
  273.  
  274.         fprintf(outfile, "  OBJECT\n");
  275.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[1]+0.01, ycoords[1], zcoords[1]);
  276.         finishobj(curcolor);
  277.                 num_lines++;
  278.         return;
  279.     }
  280.     else if (strstr(curobj, "POINT"))    /* an itty, bitty sphere! */
  281.     {
  282.         fprintf(outfile, "  OBJECT\n");
  283.         fprintf(outfile, "    SPHERE <%1.06f %1.06f %1.06f> 0.1 END_SPHERE\n", xcoords[0], ycoords[0], zcoords[0]);
  284.         finishobj(curcolor);
  285.                 num_points++;
  286.         return;
  287.     }
  288.     else if (strstr(curobj, "CIRCLE"))    /* a VERY short cylinder! */
  289.     {
  290.         fprintf(outfile, "  OBJECT\n");
  291.         fprintf(outfile, "    INTERSECTION\n");
  292.         fprintf(outfile, "      QUADRIC Cylinder_Z SCALE <%1.06f %1.06f %1.06f> END_QUADRIC\n", doubles[0], doubles[0], doubles[0]);
  293.         fprintf(outfile, "      PLANE <0.0 0.0 1.0>  0.1 END_PLANE\n");
  294.         fprintf(outfile, "      PLANE <0.0 0.0 -1.0> 0.1 END_PLANE\n");
  295.         fprintf(outfile, "    END_INTERSECTION\n");
  296.         fprintf(outfile, "    TRANSLATE <%1.06f %1.06f %1.06f>\n", xcoords[0], ycoords[0], zcoords[0]);
  297.         finishobj(curcolor);
  298.                 num_circles++;
  299.         return;
  300.     }
  301.     else if (strstr(curobj, "ARC"))        /* not implemented for now */
  302.     {
  303.         return;
  304.     }
  305.     else if (strstr(curobj, "TRACE"))    /* 2 back-to-back triangles */
  306.     {
  307.         if (checkdegen(0, 1, 2))
  308.         {
  309.             degenerates++;
  310.             return;
  311.         }
  312.  
  313.         fprintf(outfile, "  OBJECT\n");
  314.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[2], ycoords[2], zcoords[2]);
  315.                 num_traces++;
  316.         finishobj(curcolor);
  317.  
  318.         if (checkdegen(0, 3, 2))
  319.         {
  320.             degenerates++;
  321.             return;
  322.         }
  323.  
  324.         fprintf(outfile, "  OBJECT\n");
  325.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[3], ycoords[3], zcoords[3], xcoords[2], ycoords[2], zcoords[2]);
  326.         finishobj(curcolor);
  327.  
  328.         return;
  329.     }
  330.     else if (strstr(curobj, "SOLID"))    /* 1 or 2 triangles */
  331.     {
  332.         if (checkdegen(0, 1, 2))
  333.         {
  334.             degenerates++;
  335.             return;
  336.         }
  337.  
  338.         fprintf(outfile, "  OBJECT\n");
  339.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[2], ycoords[2], zcoords[2]);
  340.         finishobj(curcolor);
  341.                 num_solids++;
  342.         if (xcoords[2] == xcoords[3] && ycoords[2] == ycoords[3] && zcoords[2] == zcoords[3])
  343.             return;    /* one triangle was enough... */
  344.  
  345.         if (checkdegen(0, 3, 2))
  346.         {
  347.             degenerates++;
  348.             return;
  349.         }
  350.  
  351.         fprintf(outfile, "  OBJECT\n");
  352.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[3], ycoords[3], zcoords[3], xcoords[2], ycoords[2], zcoords[2]);
  353.         finishobj(curcolor);
  354.         return;
  355.     }
  356.     else if (strstr(curobj, "TEXT"))    /* not implemented for now */
  357.     {
  358.         return;
  359.     }
  360.     else if (strstr(curobj, "SHAPE"))    /* these look very hard */
  361.     {
  362.         return;
  363.     }
  364.     else if (strstr(curobj, "BLOCK"))    /* these look very hard */
  365.     {
  366.         return;
  367.     }
  368.     else if (strstr(curobj, "ENDBLK"))    /* these look very hard */
  369.     {
  370.         return;
  371.     }
  372.     else if (strstr(curobj, "INSERT"))    /* these look very hard */
  373.     {
  374.         return;
  375.     }
  376.     else if (strstr(curobj, "ATTDEF"))    /* not implemented for now */
  377.     {
  378.         return;
  379.     }
  380.     else if (strstr(curobj, "ATTRIB"))    /* not implemented for now */
  381.     {
  382.         return;
  383.     }
  384.     else if (strstr(curobj, "POLYLINE")) /* these look fairly hard */
  385.     {
  386.         return;
  387.     }
  388.     else if (strstr(curobj, "VERTEX"))    /* these look fairly hard */
  389.     {
  390.         return;
  391.     }
  392.     else if (strstr(curobj, "SEQEND"))    /* these look fairly hard */
  393.     {
  394.         return;
  395.     }
  396.     else if (strstr(curobj, "3DLINE"))    /* a VERY skinny triangle! */
  397.     {
  398.         if (xcoords[0] == xcoords[1] && ycoords[0] == ycoords[1] && zcoords[0] == zcoords[1])
  399.         {
  400.             degenerates++;
  401.             return;
  402.         }
  403.  
  404.         fprintf(outfile, "  OBJECT\n");
  405.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[1]+0.1, ycoords[1], zcoords[1]);
  406.         finishobj(curcolor);
  407.                 num_3dlines++;
  408.  
  409.         return;
  410.     }
  411.     else if (strstr(curobj, "3DFACE"))    /* 1 or 2 triangles */
  412.     {
  413.         if (checkdegen(0, 1, 2))
  414.         {
  415.             degenerates++;
  416.             return;
  417.         }
  418.  
  419.         fprintf(outfile, "  OBJECT\n");
  420.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[1], ycoords[1], zcoords[1], xcoords[2], ycoords[2], zcoords[2]);
  421.         finishobj(curcolor);
  422.                 num_3dfaces++;
  423.         if (xcoords[2] == xcoords[3] && ycoords[2] == ycoords[3] && zcoords[2] == zcoords[3])
  424.             return;    /* one triangle was enough... */
  425.  
  426.         if (checkdegen(0, 3, 2))
  427.         {
  428.             degenerates++;
  429.             return;
  430.         }
  431.  
  432.         fprintf(outfile, "  OBJECT\n");
  433.         fprintf(outfile, "    TRIANGLE <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> <%1.06f %1.06f %1.06f> END_TRIANGLE\n", xcoords[0], ycoords[0], zcoords[0], xcoords[3], ycoords[3], zcoords[3], xcoords[2], ycoords[2], zcoords[2]);
  434.         finishobj(curcolor);
  435.         return;
  436.     }
  437.     else if (strstr(curobj, "DIMENSION"))    /* not implemented for now */
  438.     {
  439.         return;
  440.     }
  441.     return;    /* no current object defined... */
  442. }
  443.  
  444. void finishobj(color)    /* conclude a DKB-style object definition */
  445. int color;
  446. {
  447.     double red, green, blue;
  448.  
  449.     lookupcolor(color, &red, &green, &blue);
  450.     fprintf(outfile, "    TEXTURE Dull\n");  /* default surf. */
  451.     fprintf(outfile, "      COLOR RED %1.06f GREEN %1.06f BLUE %1.06f\n", red, green, blue);
  452.     fprintf(outfile, "    END_TEXTURE\n");  /* default surf. */
  453.     fprintf(outfile, "  END_OBJECT\n\n");
  454.     printf(".");        /* activity echo (happy dots) */
  455.     primitives++;        /* count another output file primitive */
  456. }
  457.  
  458. void lookupcolor(color, red, green, blue) /* basic AutoCAD 9-color pallette */
  459. int color;
  460. double *red, *green, *blue;
  461. {
  462.     switch (color)
  463.     {
  464.         case 0:    /* black */
  465.             *red = *green = *blue = 0.0;
  466.             break;
  467.         case 1: /* red */
  468.             *red = 1.0;
  469.             *blue = *green = 0.0;
  470.             break;
  471.         case 2: /* yellow */
  472.             *red = *green = 1.0;
  473.             *blue = 0.0;
  474.             break;
  475.         case 3:    /* green */
  476.             *green = 1.0;
  477.             *red = *blue = 0.0;
  478.             break;
  479.         case 4: /* cyan */
  480.             *blue = *green = 1.0;
  481.             *red = 0.0;
  482.             break;
  483.         case 5: /* blue */
  484.             *blue = 1.0;
  485.             *red = *green = 0.0;
  486.             break;
  487.         case 6: /* magenta */
  488.             *blue = *red = 1.0;
  489.             *green = 0.0;
  490.             break;
  491.         case 8:    /* dk. grey */
  492.             *red = *green = *blue = 0.5;
  493.             break;
  494.         case 9: /* lt. grey */
  495.             *red = *green = *blue = 0.75;
  496.             break;
  497.         case 7: /* white */
  498.         default: /* make anything else white (?) */
  499.             *red = *green = *blue = 1.0;
  500.     }
  501.     return;
  502. }
  503.  
  504. int checkdegen(a, b, c)        /* check for degenerate triangle structure */
  505. int a, b, c;
  506. {
  507.     if (
  508.     (xcoords[a] == xcoords[b] &&
  509.      ycoords[a] == ycoords[b] &&
  510.      zcoords[a] == zcoords[b]) || 
  511.     (xcoords[b] == xcoords[c] &&
  512.      ycoords[b] == ycoords[c] &&
  513.      zcoords[b] == zcoords[c]) || 
  514.     (xcoords[a] == xcoords[c] &&
  515.      ycoords[a] == ycoords[c] &&
  516.      zcoords[a] == zcoords[c]))
  517.         return(1);
  518.     return(0);
  519. }
  520.